package cn.tyz.kotlin.ui

import android.os.Bundle
import cn.tyz.kotlin.R
import cn.tyz.kotlin.utils.LogUtil

/**
 * @author : tyz
 * @ClassName: Note11CollectionsActivity
 * @Description: 集合 区间
 * @time 2018/5/21 0:06
 * https://blog.csdn.net/csdn_gyg/article/details/73327735
 * https://kymjs.com/code/2017/06/06/01/
 *目前只支持返回这些对象：

    这些方法的返回值实际上返回的是 Java 的集合对象
    java.util.ArrayList
    java.util.LinkedHashMap
    java.util.HashMap
    java.util.LinkedHashSet
    java.util.HashSet
    java.util.SortedSet
    java.util.TreeSet

 * 所有类声明的泛型尖括号里面如果加入了 out 关键字，则说明这个类的对象是只读的，例如他只有：get()、size（）等方法，而没有 set()、remove()等方法。
相反的，如果没有加 out 关键字，或者换一种记法：如果开头是 MutableXXX 那就是一个跟 Java 中用法一致的集合类。
        out 关键字，则说明这个类的对象是只读的 ;与 out 对应的，还有一个 in。表示泛型参数是只写的。
 */

class Note11CollectionsActivity: BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.act_common)
        foo()
        showRange()
        showTotalOP()
        showFilterOP()
        showMapOP()
    }


    fun foo(){
        LogUtil.i("集合的初始化")
        var readOnlyList:List<Int>//声明一个只读list
        var mutableList= mutableListOf<Int>(1,2,3)//创建一个可变list并初始化
        readOnlyList=mutableList//赋值可变list给只读list，这样两者指向相同的底层list,只读list会随着可变list的改变而改变
        print(readOnlyList)//[1,2,3]
        mutableList.add(4)//通过可变list修改底层list
        print(readOnlyList)//[1,2,3,4]

        val emptyList = emptyList<String>()
        val commonList = listOf(1,2,3)

        var readOnlySet:Set<Int>//声明一个制度set
        var mutableSet= mutableSetOf<Int>(1,2,3)//创建一个可变set并初始化
        readOnlySet=mutableSet//赋值可变set给只读set，这样两者指向相同的底层set,只读set会随着可变set的改变而改变
        print(readOnlySet)//[1,2,3]
        mutableSet.add(4)//通过可变list修改底层list
        print(readOnlySet)//[1,2,3,4]

        val hashSet = hashSetOf(1,2,3)
        val linkedSet = linkedSetOf(1,2,3)
        val sortedSetO = sortedSetOf(1,2,3)

        var readOnlyMap:Map<Int,Int>//声明一个只读map
        var mutableMap= mutableMapOf<Int,Int>()//创建一个可变Map
        readOnlyMap=mutableMap//赋值可变map给只读map，这样两者指向相同的底层map,只读map会随着可变map的改变而改变
        mutableMap.put(0,1)
        mutableMap.put(1,2)
        mutableMap.put(2,3)
        for ((key,value) in readOnlyMap){
            LogUtil.i("$value,")//1,2,3,
        }

        val mMap = mutableMapOf(1 to "order", 2 to "pig")  // 这的键值对用 to 关键字，key to value！

//        如果我们只想要一个不可变的集合，可以这样创建：
        var list= arrayListOf<Int>(1,2,3)//创建一个不可变的list并初始化
        var set= setOf<Int>(1,2,3)//创建一个不可变的set并初始化
        var map= hashMapOf<Int,Int>(0 to 1,1 to 2,2 to 3)//创建一个不可变的map并初始化


//        也可以生成一个集合在当前时刻的一个快照，返回一个保障不会变的集合：
        var copyList=mutableList.toList()//toList方法只是复制列表项，因此返回的 list 保证永远不会改变。
        var copySet=mutableSet.toSet()//toSet方法只是复制列表项，因此返回的 set 保证永远不会改变。
        var copyMap=mutableMap.toMap()//oMap方法只是复制列表项，因此返回的 map 保证永远不会改变。
    }

    fun showRange(){
        for (num in 1..10){
            LogUtil.i("$num")
        }

        for (num in 10 downTo 1){ // 倒序
            LogUtil.i("$num")
        }

        for (num in 1..10 step 2){//步长为2
            LogUtil.i("$num")
        }

        for (num in 1 until 10 step 2){//until 不包含结束元素
            LogUtil.i("$num")
        }

        (1..12 step 2).last == 11
        (1..12 step 3).last == 10
        (1..12 step 4).last == 9
    }


    open class AA
    class TypeArray<in AA> {

        //in 修饰了 AA，表示 AA 是可以作为参数的。
        fun getValue(a: AA): Int? {
            return a?.hashCode()
        }

        //这段代码是非法的，因为A 不能被返回
        /*fun getA(a: AA): AA? {
            return a
        }*/
    }

  /**    6.4 操作符
 Kotlin中关于集合的操作符有六类：
  https://www.2cto.com/kf/201611/567100.html
  https://www.jianshu.com/p/8f32de00c5dc
总数操作符 过滤操作符 映射操作符 顺序操作符 生产操作符 元素操作符
  1）总数操作符
  any —— 判断集合中 是否有满足条件 的元素；
  all —— 判断集合中的元素 是否都满足条件；
  none —— 判断集合中是否 都不满足条件，是则返回true；
  count —— 查询集合中 满足条件 的 元素个数；
  reduce —— 从 第一项到最后一项进行累计 ；
  reduceRight —— 从 最后一下到第一项进行累计；
  fold —— 与reduce类似，不过有初始值，而不是从0开始累计；
  foldRight —— 和reduceRight类似，有初始值，不是从0开始累计；
  forEach —— 循环遍历元素，元素是it，可对每个元素进行相关操作；
  forEachIndexed —— 循环遍历元素，同时得到元素index(下标)；
  max —— 查询最大的元素，如果没有则返回null；
  maxBy —— 获取方法处理后返回结果最大值对应的那个元素的初始值，如果没有则返回null；
  min —— 查询最小的元素，如果没有则返回null；
  minBy —— 获取方法处理后返回结果最小值对应那个元素的初始值，如果没有则返回null；
  sumBy —— 获取 方法处理后返回结果值 的 总和；
  dropWhile —— 返回从第一项起，去掉满足条件的元素，直到不满足条件的一项为止

   */
    fun showTotalOP(){
      LogUtil.i("================Kotlin中关于集合的操作符有六类================")
      LogUtil.i("================通过操作符将list转换================")
        var wifiPwd  = "?"
        val a = arrayOf("0","1","2","6","7","h","j")
        val indexArray = arrayOf(5,9,6,8,2,7,0,1,4,0,3)
        wifiPwd = indexArray
                .filter { it in 0 until a.size }    // 过滤
                .map { a[it] }  // 转换
                .reduce{
                    s1,s2 -> "$s1$s2"
                }

        LogUtil.i("$wifiPwd")
        val list: List<String> = listOf("hello","world")
        list.convert {
            it.hashCode()
        }.forEach {
            LogUtil.i("$it")
        }
        LogUtil.i(" ================ 总数操作符 ================")
        LogUtil.i("操作符======= indexArray.any{ it >5 } ="+indexArray.any{ it >5 })
        LogUtil.i("操作符======= indexArray.all{ it >5 } = "+indexArray.all{ it >5 })
        LogUtil.i("操作符======= indexArray.none{ it %2==0 =} "+indexArray.none{ it %2==0 })
        LogUtil.i("操作符======= indexArray.count{ it >5 } = "+indexArray.count{ it >5 })
        LogUtil.i("操作符======= indexArray.reduce{ total, next -> total + next } = "+indexArray.reduce{ total, next -> total + next })
        LogUtil.i("操作符======= indexArray.reduceRight{ total, next -> total + next } = "+indexArray.reduceRight{ total, next -> total + next })
        LogUtil.i("操作符======= indexArray.fold(2){total, next -> total + next } = "+indexArray.fold(2){ total, next -> total + next })
        LogUtil.i("操作符======= indexArray.foldRight(2){total, next -> total + next } = "+indexArray.foldRight(2){ total, next -> total + next })
        LogUtil.i("操作符======= indexArray.forEach(::print) = "+indexArray.forEach(::print))
        LogUtil.i("操作符======= indexArray.forEach{} = "+indexArray.forEach{LogUtil.i("$it")})
        LogUtil.i("操作符======= indexArray.forEachIndexed{} = "+indexArray.forEachIndexed{index, it -> LogUtil.i("$index: $it")  })
        LogUtil.i("操作符======= indexArray.max() = "+indexArray.max())
        LogUtil.i("操作符======= indexArray.maxBy() = "+indexArray.maxBy { it * (indexArray.size - it) })
        LogUtil.i("操作符======= indexArray.min() = "+indexArray.min())
        LogUtil.i("操作符======= indexArray.minBy() = "+indexArray.minBy { it * (indexArray.size - it) })

    }

    fun showFilterOP(){
        /** filter —— 过滤 掉所有 满足条件 的元素
         * filterNot —— 过滤所有不满足条件的元素
         * filterNotNull —— 过滤NULL
         * take —— 返回从第一个开始的n个元素
         * takeLast —— 返回从最后一个开始的n个元素
         * takeWhile —— 返回不满足条件的下标前面的所有元素的集合
         * drop —— 返回 去掉前N个元素后 的列表
         * dropLastWhile —— 返回从最后一项起，去掉满足条件的元素，直到不满足条件的一项为止
         * slice —— 过滤掉 非指定下标 的元素，即保留下标对应的元素过滤list中
        指定下标的元素(比如这里只保留下标为1,3,4的元素)*/
        LogUtil.i(" ================ 过滤操作符  不会改变原列表================")
        val fList = arrayOf(5,9,6,8,2,7,0,1,4,null)
        LogUtil.i("原始数据       "+fList.toList())
        LogUtil.i("filter        "+fList.filter { it !=3 })
        LogUtil.i("filterNot     "+fList.filterNot { it ==3 })
        LogUtil.i("filterNotNull "+fList.filterNotNull())
        LogUtil.i("take          "+ fList.take(4))
        LogUtil.i("takeLast      "+fList.takeLast(4))
        LogUtil.i("takeWhile     "+fList.takeWhile { it!!<4 })
        LogUtil.i("drop          "+fList.drop(4))
        LogUtil.i("dropWhile      "+fList.dropWhile { it!!<3 })
        LogUtil.i("dropLastWhile  "+fList.dropLastWhile { it == null })
        LogUtil.i("slice          "+fList.slice( 2..5))
    }

    fun showMapOP(){
        /** map —— 将集合中的元素通过某个 方法转换 后的结果存到一个集合中;
         * mapIndexed —— 除了得到 转换后的结果 ，还可以拿到Index(下标);
         * mapNotNull —— 执行方法 转换前过滤掉 为 null 的元素, 过滤的是表达式的结果
         * flatMap —— 自定义逻辑合并两个集合；
         * groupBy —— 将集合中的元素按照某个条件分组，返回Map；*/
        LogUtil.i(" ================ 映射操作符================")
        val list1 = arrayOf(1,2,3,4,5)
        val list2 = arrayOf(6,7,8,9,10)
        val list3 = arrayOf("a",null,"b","c",null) //
        LogUtil.i("原始数据       "+list1.toList())
        LogUtil.i("原始数据       "+list1.map { it +1000 })
        LogUtil.i("mapIndexed     "+list2.mapIndexed{i,it -> i*100 +it})
        LogUtil.i("mapNotNull     "+list3.mapNotNull{ it }) //  [a, b, c]
        LogUtil.i("mapNotNull     "+list2.mapNotNull{ it>7 }) // [false, false, true, true, true]
        LogUtil.i("flatMap        "+list1.flatMap { listOf(it, it + 1) }) // [1, 2, 2, 3, 3, 4, 4, 5, 5, 6]
        LogUtil.i("flatMap        "+listOf(list1, list2) ) //
        LogUtil.i("flatMap        "+listOf(list1, list2).flatMap{ listOf(it, it +1) } ) // [1, 2, 2, 3, 3, 4, 4, 5, 5, 6]
        LogUtil.i("groupBy        "+list2.groupBy { if (it % 2 == 0) "even" else "odd" }) // {even=[6, 8, 10], odd=[7, 9]}
//        https://www.cnblogs.com/tgyf/p/6892551.html?utm_source=itdadao&utm_medium=referral

    }

    inline fun <T, E> Iterable<T>.convert(action: (T) -> E): MutableList<E> {
        val list: MutableList<E> = mutableListOf()
        for (element in this) list.add(action(element))
        return list
    }
}
